#ifndef _XS_LINUX_H__
#define _XS_LINUX_H__

#define LINUX

/*============================= Include Files ===============================*/
/* Semaphore type definition 
**
** Include files needed for defining OS-specific functions and semaphore data types 
** Counting semaphore - a semaphore type which supports value increment and decrement 
*/
#if defined WIN32
	#define _WIN32_WINNT 0x0400 /* Will not work on old NT versions */
	#include <windows.h>
	#include <time.h>
	
    	typedef HANDLE           xs_counting_semaphore_t;
	typedef SOCKET XSOCKET;

#elif defined LINUX
    #include <semaphore.h> /* Counting semaphore definitions header */
    #include <pthread.h>

    typedef pthread_t         		xs_pthread_t;
    typedef sem_t			  	xs_counting_semaphore_t;

    typedef pthread_attr_t		xs_pthread_attr_t;
    typedef pthread_mutex_t	  	xs_pthread_mutex_t;
    typedef pthread_mutexattr_t		xs_pthread_mutex_attr_t;
	
    typedef pthread_cond_t			xs_pthread_cond_t;
    typedef pthread_condattr_t		xs_pthread_cond_attr_t;

    typedef xs_counting_semaphore_t xs_semaphore_t;

	typedef int XSOCKET;
	
#elif defined VXWORKS
	#include <VxWorks.h>
	#include <semLib.h>
	#include <types/vxTypes.h>
	#include <vxWorks.h> 
	#include <net/uio.h>
	#include <sys/times.h>
    typedef SEM_ID			 xs_counting_semaphore_t;
#else
    #error Unsupported OS

/* Note: Other OSs semaphore type definition should be placed here */
#endif

//#include "../PON/PON_xs_defs.h"

/*================================ Macros ===================================*/
/*=============================== Constants =================================*/
#define MAXPATHLEN		4096
/*============================== Data Types =================================*/

/* definition of the iovec structure exactly as it defined in LINUX "sys/uio.h" */ 
#ifdef WIN32

   struct iovec {
     char *iov_base;
     size_t iov_len;
   };

typedef unsigned int  uid_t;
typedef unsigned int  gid_t;

typedef unsigned int    u_int32_t;
typedef unsigned short  u_int16_t;
typedef unsigned char   u_int8_t;

struct timezone {
int     tz_minuteswest; /* minutes W of Greenwich */
int     tz_dsttime;     /* type of dst correction */
};

#elif defined VXWORKS

#ifndef u_int32_t 
typedef unsigned int    u_int32_t;
#endif

#ifndef u_int16_t 
typedef unsigned short  u_int16_t;
#endif

#ifndef u_int8_t 
typedef unsigned char   u_int8_t;
#endif

#endif  /*VXWORKS*/



__BEGIN_DECLS




/* xs_wait
** 
** Wait (do nothing) for the parametered time and then return.
**
** Assumption: the function has a thread resolution (only the calling thread is on hold) 
** and it is thread-hot (several threads can call it simultaneously without affecting each other).
**
** Input parameter:
**				msec	   : Time in milliseconds, range: type range (0 - 65535 (~1 min))
**
** Return codes:
**				EXIT_OK    : Success
**				EXIT_ERROR : Error 
*/
int xs_wait ( unsigned short int );


/* Thread function */
typedef void (*xs_thread_function_t) ( void * );

/* xs_create_thread
**
** Create a new thread, and initializes it with the parametered function. 
** The thread starts to run and the function returns.
** 					
** Input parameter:
**				thread_function	: Pointer to a thread function,
**								  function prototype: xs_thread_function_t
** Return codes:
**				0				: Error / Thread id not available
**				other			: New thread id
*/
unsigned long xs_create_thread ( void*(*__thread_func)(void *) );
unsigned long xs_pthread_create (void*(*__thread_func__)(void *), void  *__arg__);

/* xs_create_thread_with_arg
**
** Create a new thread, and initializes it with the parametered function and one argument. 
** The thread starts to run and the function returns.
** 					
** Input parameter:
**				thread_function	: Pointer to a thread function,
**								  function prototype: xs_thread_function_t
**				arg          	: argument which will be passed to the thread function
** Return codes:
**				0				: Error / Thread id not available
**				other			: New thread id
*/
//unsigned long xs_create_thread_with_arg (void*(*__thread_func)(void *), void  * );

/* xs_terminate_thread
**
** This function is used by a thread to terminate itself
**
** Parameters:
**
** Return codes:
**
*/
void xs_pthread_exit (void);
int xs_pthread_join ( xs_pthread_t , void **);

int xs_pthread_attr_init(xs_pthread_attr_t *);
int xs_pthread_attr_destroy(xs_pthread_attr_t *);

int xs_pthread_mutex_init(xs_pthread_mutex_t *,
                          const xs_pthread_mutex_attr_t *);

int xs_pthread_mutex_lock(xs_pthread_mutex_t *);

int xs_pthread_mutex_trylock(xs_pthread_mutex_t *);

int xs_pthread_mutex_unlock(xs_pthread_mutex_t *);

int xs_pthread_mutex_destroy(xs_pthread_mutex_t *);

int xs_pthread_mutex_timedlock(xs_pthread_mutex_t *, const long );


/* xs_counting_semaphore_init
** 
** Init a counting semaphore.
** Only after a counting semaphore has been init, it can be used (post and wait).
**
** Input parameters:
**				semaphore     : Counting semaphore id
**				initial_value : Initial count associated with the counting semaphore, range: 0 - MAXINT
**
** Return codes:
**				EXIT_OK		  : Success
**				EXIT_ERROR	  : Init error
*/
int xs_counting_semaphore_init (xs_counting_semaphore_t  *,
                                const unsigned short int );


/* xs_counting_semaphore_post
** 
** Atomically increase the count of a counting semaphore.  
** This function never blocks the semaphore and can safely be used in asynchronous signal handlers.
**
** Input parameter:
**				semaphore	: Counting semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Post error
*/
int xs_counting_semaphore_post (xs_counting_semaphore_t  *);


/* xs_counting_semaphore_wait
**
** Suspend the calling thread until the counting semaphore has a non-zero count,  
** then atomically decreases the semaphore count.
**
** Input parameter:
**				semaphore	: Counting semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Wait error
*/
int xs_counting_semaphore_wait (xs_counting_semaphore_t*);


/* xs_counting_semaphore_trywait
**
** This is a non-blocking variant of xs_counting_semaphore_wait.
** If the counting semaphore has a non-zero count, the count is atomically decreased and the function
** immediately returns 'success'. If the semaphore count is zero, the function immediately returns with
** the code 'failed'.
**
** Input parameter:
**				semaphore	: Counting semaphore id
**
** Return codes:
**				0			: Wait failed (semaphore count is zero)
**				1			: Wait success (semaphore count is non-zero)
**				EXIT_ERROR	: Wait error (e.g. counting semaphore is not valid)
*/
int xs_counting_semaphore_trywait ( xs_counting_semaphore_t* );


/* xs_counting_semaphore_wait
**
** Suspend the calling thread until the counting semaphore has a non-zero count,  
** then atomically decreases the semaphore count.
**
** Input parameter:
**				semaphore	 : Counting semaphore id
**              milliseconds : time-out interval in milliseconds
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Wait error
**              TIME_OUT    : Time out wating to the semaphore 
*/              
int xs_counting_semaphore_wait_timeout ( xs_counting_semaphore_t  *,
                                         long int  );


/* xs_counting_semaphore_close
**
** Close a counting semaphore.
** After a counting semaphore has been closed, the only manipulation it supports is init.
**
** Input parameter:
**				semaphore	: Counting semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Close error
*/
int xs_counting_semaphore_destroy (xs_counting_semaphore_t *);


int xs_pthread_cond_init(xs_pthread_cond_t *__cond, xs_pthread_cond_attr_t *__attr);
int xs_pthread_cond_signal(xs_pthread_cond_t *__cond);
int xs_pthread_cond_broadcast(xs_pthread_cond_t *__cond);
int xs_pthread_cond_wait(xs_pthread_cond_t * __cond, xs_pthread_mutex_t *__mutex);
int xs_pthread_cond_timedwait(xs_pthread_cond_t *__cond, xs_pthread_mutex_t *__mutex, unsigned long __noseconds);
int xs_pthread_cond_destroy(xs_pthread_cond_t *__cond);

int xs_gettimeofday (struct timeval * , struct timezone *);
char *xs_getcwd ( char *__buf, int __len);
int xs_getpagesize(void);


/* xs_semaphore_init
**
** Initialize a semaphore / mutex or other thread hot sync mechanism.
** Only after a semaphore has been init, it can be used (signal and release).
**
** Input parameter:
**				semaphore	: Semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Init error
*/
#define xs_semaphore_init(semaphore)    xs_counting_semaphore_init(semaphore, 1)


/* xs_semaphore_signal
** 
** 'Signal' a semaphore.
** After a semaphore has been 'signaled', it can be either released by the signaling thread 
** (multi signaling is unspecified) or signaled by other threads (waiting threads).
**
** Input parameter:
**				semaphore	: Semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Signal error
*/
#define xs_semaphore_signal(semaphore)  xs_counting_semaphore_wait(semaphore)


/* xs_semaphore_release
**
** 'Release' a semaphore.
** After the semaphore has been 'released', any thread may signal it again.
**
** Input parameter:
**				semaphore	: Semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Release error (e.g. semaphore is not signaled)
*/
#define xs_semaphore_release(semaphore) xs_counting_semaphore_post(semaphore)


/* xs_semaphore_listen
** 
** 'Listen' to a semaphore and signal it if possible.
** The function attempts once to signal a semaphore without blocking. 
** It returns a code indicating whether the signal attempt succeeded. After a semaphore has been 
** 'signaled', it can be either released by the signaling thread or signaled by other threads (waiting
** threads). Multi listening (same thread listening a semaphore again and again after it signaled the  
** semaphore) is unspecified.
**
** Input parameter:
**				semaphore	: Semaphore id
**
** Return codes:
**				0			: Listen failed (another thread owns the semaphore)
**				1			: Listen success (semaphore is signaled by current thread)
**				EXIT_ERROR	: Listen error (e.g. semaphore is not valid)
*/
#define xs_semaphore_listen(semaphore)  xs_counting_semaphore_trywait(semaphore)


/* xs_semaphore_close
**
** Close a semaphore.
** After a semaphore has been closed, the only function applicable upon it is xs_semaphore_init.
**
** Input parameter:
**				semaphore	: Semaphore id
**
** Return codes:
**				EXIT_OK		: Success
**				EXIT_ERROR	: Close error
*/
#define xs_semaphore_close(semaphore)   xs_counting_semaphore_destroy(semaphore)

__END_DECLS

#endif

